Multiplexed Server Design হল একটি নেটওয়ার্ক সার্ভারের ডিজাইন প্যাটার্ন যেখানে একাধিক ক্লায়েন্টের সাথে একযোগে যোগাযোগ পরিচালনা করা হয়, সাধারণত একটি একক থ্রেড বা প্রসেসের মাধ্যমে। এটি সিস্টেমের স্কেলেবিলিটি এবং পারফরম্যান্স বৃদ্ধির জন্য ব্যবহৃত হয়, কারণ এতে একাধিক ক্লায়েন্টের জন্য আলাদা থ্রেড তৈরি করার প্রয়োজন হয় না। এর বদলে, সিস্টেম একযোগে একাধিক সংযোগ পরিচালনা করতে select()
, poll()
, বা epoll()
ব্যবহার করে, যা সকেট I/O এর জন্য অপেক্ষা না করে একাধিক কানেকশনের সাথে কাজ করতে সাহায্য করে।
এই ডিজাইনটি সাধারণত একটি ইভেন্ট-ড্রিভেন আর্কিটেকচার, যেখানে সার্ভার শুধুমাত্র সকেট I/O এর জন্য অপেক্ষা করে এবং যেকোনো সকেট যদি প্রস্তুত থাকে (যেমন ডেটা আসা), তখন সে সকেটটির সাথে ইন্টারঅ্যাক্ট করে।
এখানে একটি Multiplexed TCP Server এর উদাহরণ দেখানো হলো যা একাধিক ক্লায়েন্টের সাথে নন-ব্লকিং I/O এবং select()
ব্যবহারের মাধ্যমে কাজ করে। এই সার্ভার একযোগে অনেক ক্লায়েন্টের সাথে সংযোগ স্থাপন এবং ডেটা গ্রহণ করে, তবে একাধিক থ্রেড বা প্রসেস ব্যবহৃত হয় না।
select()
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/select.h>
#include <arpa/inet.h>
#define PORT 65432
#define MAX_CLIENTS 10
int main() {
int server_socket, client_socket, max_sd;
struct sockaddr_in server_addr, client_addr;
socklen_t client_len = sizeof(client_addr);
char buffer[1024];
fd_set readfds;
// সার্ভার সকেট তৈরি
server_socket = socket(AF_INET, SOCK_STREAM, 0);
if (server_socket == -1) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}
// সার্ভারের IP এবং পোর্ট সেট করা
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(PORT);
// সার্ভার সকেটে বাইন্ড করা
if (bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
perror("Bind failed");
exit(EXIT_FAILURE);
}
// লিসেনিং শুরু করা
if (listen(server_socket, 5) == -1) {
perror("Listen failed");
exit(EXIT_FAILURE);
}
printf("Server is listening on port %d...\n", PORT);
// `select()` ব্যবহারের জন্য সকেট সেটআপ
FD_ZERO(&readfds);
FD_SET(server_socket, &readfds);
max_sd = server_socket;
// ক্লায়েন্টের সংযোগের জন্য অপেক্ষা
while (1) {
fd_set tempfds = readfds;
int activity = select(max_sd + 1, &tempfds, NULL, NULL, NULL);
if (activity == -1) {
perror("select error");
exit(EXIT_FAILURE);
}
// নতুন সংযোগ পাওয়া গেলে
if (FD_ISSET(server_socket, &tempfds)) {
client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &client_len);
if (client_socket == -1) {
perror("Accept failed");
continue;
}
printf("New client connected\n");
FD_SET(client_socket, &readfds);
if (client_socket > max_sd) max_sd = client_socket;
}
// সকেট থেকে ডেটা পড়া
for (int i = 0; i <= max_sd; i++) {
if (FD_ISSET(i, &tempfds)) {
int valread = read(i, buffer, sizeof(buffer));
if (valread == 0) {
printf("Client disconnected\n");
close(i);
FD_CLR(i, &readfds);
} else {
printf("Received from client: %s\n", buffer);
send(i, "Message received", 16, 0);
}
}
}
}
close(server_socket);
return 0;
}
socket()
ফাংশন দিয়ে একটি TCP সকেট তৈরি করা হয়েছে এবং bind()
এর মাধ্যমে এটি একটি নির্দিষ্ট পোর্টে বাইন্ড করা হয়েছে।select()
ব্যবহারের জন্য সেটআপ: সার্ভার select()
ফাংশন ব্যবহার করে সকেটের উপর নজর রাখছে, এবং যখন কোনো নতুন ক্লায়েন্ট সংযোগ স্থাপন করবে, তখন সেই সকেটকে readfds
সেটে যোগ করা হবে।accept()
ফাংশন ব্যবহার করে সংযোগ গ্রহণ করা হয়।select()
ফাংশনটি একযোগে একাধিক ক্লায়েন্টের সংযোগ এবং ডেটা প্রক্রিয়া করতে সক্ষম।Multiplexed Server Design হল একটি শক্তিশালী এবং স্কেলেবল নেটওয়ার্ক আর্কিটেকচার প্যাটার্ন, যেখানে একাধিক ক্লায়েন্টকে একযোগভাবে পরিচালনা করা যায়। select()
, poll()
, বা epoll()
ফাংশন ব্যবহার করে এই ধরনের সার্ভার ডিজাইন তৈরি করা সম্ভব, যা কম রিসোর্সে অধিক কার্যকারিতা প্রদান করে এবং সিস্টেমের স্কেলেবিলিটি বাড়ায়।
common.read_more